#coding:utf-8
from django.db import models
from django.contrib.auth.models import User
import datetime, time

def response_format(item_list, err_description=""):
    """define response format for client func"""
    return {"value": err_description == "",
            "desp": err_description,
            "data": item_list}

class ISQL(models.Model):
    """relationship datebase models"""
    author = models.ForeignKey(User)
    is_del = models.BooleanField(default=False)
    birthtime = models.PositiveIntegerField(default=0)
    birthday = models.PositiveIntegerField(default=0)
    name = models.CharField(max_length="40", default="")
    class Meta:
        """Meta class in Django"""
        abstract = True
        ordering = "pk"
    relation_dict = {
        "pk": "id",
        "pk_list": "id_list",
        "author_id": "use_id",
        "is_del": "is_del",
        "birthtime": "birthtime",
        "birthday": "birthday",
        "name": "name",
    }
    values_args = ["pk", "author_id", "name", "birthtime", "birthday"]
    @classmethod
    def get_kwargs(cls, base_arg_dict, kwargs):
        """return valid kwargs.
        get_kwargs(["pk"], {"pk": 1, "name": "lhmc"}) will return {"pk": 1}"""
        return_kwargs = {}
        for arg_name in base_arg_dict:
            if arg_name in kwargs:
                return_kwargs[arg_name] = kwargs[arg_name]
        return return_kwargs
    # #############
    # CRUD
    # #############
    create_arg_list = ["author_id", "name"]
    update_arg_list = ["name", "is_del",]
    update_forginkey_dict = {}
    search_arg_dict = {
        "pk": "pk",
        "pk_list": "pk__in",
        "author_id": "author_id",
        "birthtime": "birthtime",
        "birthday": "birthday",
        "name": "name__contains",
    }
    @classmethod
    def get_create_kwargs(cls, kwargs):
        """return valid kwargs for create. It used cls.create_arg_list as valid args list.
        args: kwargs, dict as {"age": 100, "name": "lhmc"}
        EX. create_arg_list = ["name"]
        get_create_kwargs({"age": 100, "name": "lhmc"}) will return {"name": "lhmc"}
        "create_arg_list" and "get_create_kwargs()" could be rewrite in child class"""
        create_kwargs = cls.get_kwargs(cls.create_arg_list, kwargs)
        if not "author_id" in create_kwargs:
            create_kwargs["author_id"] = kwargs["login_user_id"]
        create_kwargs["birthtime"] = int(time.time())
        create_kwargs["birthday"] = int(datetime.date.today().isoformat().replace("-", ""))
        return create_kwargs
    @classmethod
    def create(cls, kwargs):
        """use objects.create to create row in database"""
        create_kwargs = cls.get_create_kwargs(kwargs)
        return cls.objects.create(**create_kwargs)
    @classmethod
    def dele(cls, item_pk):
        """Set "is_del" as True so that no item will be deleted in system."""
        return cls.search({"pk":item_pk}).update(is_del=True)
    @classmethod
    def get_update_kwargs(cls, kwargs):
        """return valid kwargs for update. It used cls.update_arg_list as valid args list.
        args: kwargs, dict as {"age": 100, "name": "lhmc"}
        EX. update_arg_list = ["name"]
        get_update_kwargs({"age": 100, "name": "lhmc"}) will return {"name": "lhmc"}
        "update_arg_list" and "get_update_kwargs()" could be rewrite in child class"""
        update_kwargs = cls.get_kwargs(cls.update_arg_list, kwargs)
        for server_var, forgin_key in cls.update_forginkey_dict.iteritems():
            if server_var in update_kwargs:
                update_kwargs[forgin_key] = update_kwargs[server_var]
                del update_kwargs[server_var]
        return update_kwargs
    @classmethod
    def update(cls, item_pk, kwargs):
        """use objects.update to update rows in database"""
        update_kwargs = cls.get_update_kwargs(kwargs)
        return cls.search({"pk":item_pk}).update(**update_kwargs)
    @classmethod
    def get_search_kwargs(cls, kwargs):
        """return valid kwargs for search. It used cls.search_arg_dict as valid args list.
        args: kwargs, dict as {"age": 100, "name": "lhmc"}
        EX. search_arg_dict = {"name": "name_contains", "pk_list": "pk__in" }
        get_search_kwargs({"pk_list": [1,2], "name": "lhmc"})
        will return {"pk__in": [1,2], "name_contains": "lhmc"}
        "search_arg_dict" and "get_search_kwargs()" could be rewrite in child class"""
        search_kwargs = {}
        for arg_name, search_arg_name in cls.search_arg_dict.iteritems():
            if arg_name in kwargs:
                search_kwargs[search_arg_name] = kwargs[arg_name]
        search_kwargs["is_del"] = False
        return search_kwargs
    @classmethod
    def search(cls, kwargs):
        """use filter to search rows in database"""
        search_kwargs = cls.get_search_kwargs(kwargs)
        return cls.objects.filter(**search_kwargs).distinct()
    # ################
    # response format
    # ################
    @classmethod
    def get_values(cls, kwargs):
        return cls.search(kwargs).values(*cls.values_args)
    @classmethod
    def create_rf(cls, **kwargs):
        """Useing create function in class and return as defined format"""
        item = cls.create(kwargs)
        item_value_set = cls.get_values({"pk": item.pk})
        return response_format(list(item_value_set))
    @classmethod
    def dele_rf(cls, item_pk, **kwargs):
        """Useing del function in class and return as defined format"""
        item_count = cls.dele(item_pk)
        if item_count < 1:
            err_description = "No such item."
            item_value_list = []
        else:
            err_description = ""
            item_value_list = list(cls.get_values({"pk": item.pk}))
        return response_format(item_value_list, err_description)
    @classmethod
    def update_rf(cls, item_pk, **kwargs):
        """Useing update function in class and return as defined format"""
        item_count = cls.update(item_pk, kwargs)
        if item_count < 1:
            err_description = "No such item."
            item_value_list = []
        else:
            err_description = ""
            item_value_list = list(cls.get_values({"pk": item.pk}))
        return response_format(item_value_list, err_description)
    @classmethod
    def search_rf(cls, **kwargs):
        """Useing search function in class and return as defined format"""
        item_value_set = cls.get_values(kwargs)
        return response_format(list(item_value_set))
class SQL_M2M(models.Model):
    class Meta:
        """Meta class in Django"""
        abstract = True
        ordering = "pk"
    main_key = ""
    another_key = ""
    another_key_list = ""
    relation_dict = {}
    @classmethod
    def create(cls, main_id, another_list):
        me_list=[]
        for item_id in another_list:
            me_list.append(cls(**{
                cls.main_key: main_id,
                cls.another_key: item_id,
            }))           
        cls.objects.bulk_create(me_list)
    @classmethod
    def update(cls, main_id, another_list):
        cls.objects.filter(**{
            cls.main_key: main_id,
        }).delete()
        cls.create(main_id, another_list)
    @classmethod
    def search(cls, main_id):
        return cls.objects.filter(**{
            cls.main_key: main_id,
        }).values(cls.another_key)
    @classmethod
    def create_rf(cls, **kwargs):
        main_id = kwargs(cls.main_key)
        another_list = kwargs(cls.another_key_list)
        cls.create(main_id, another_list)
        return_list = list(cls.search(main_id))
        return response_format(return_list)
    @classmethod
    def update_rf(cls, **kwargs):
        main_id = kwargs(cls.main_key)
        another_list = kwargs(cls.another_key_list)
        cls.update(main_id, another_list)
        return_list = list(cls.search(main_id))
        return response_format(return_list)
    @classmethod
    def search_rf(cls, **kwargs):
        main_id = kwargs(cls.main_key)
        return_list = list(cls.search(main_id))
        return response_format(return_list)

